#include "cli_api.h"
#include "img_cli_deal.h"
#ifndef AOS_BOARD_TX510_EG_SD
#include "sfh4775s.h"
//#include "ov9282_drv.h"
#else
#include "aos/kernel.h"
#include "sfh4775s.h"
#include "gc1054_drv.h"
#endif
#include "para_scan_task.h"
#include "para_traverse_task.h"
#include "image_proc.h"
#include "image_task.h"
#include "expo_para.h"
#include <string.h>


extern int aos_task_delete(char *name);

extern volatile uint32_t g_ir_mode;
#ifndef AOS_BOARD_TX510_EG_SD
regval_list ov9282_cfg_info[1] = {0};
#endif
scan_para_t scan_para_list = { 
        {IR_CURRENT_REG, 0x0},      //ir
        {SPK_CURRENT_REG, 0x0},     //spk
        {   {0x3501, 0x0},	        //expo H		
            {0x3502, 0x0},          //expo L
            {0x3509, 0x0},          //gain
        },
        0,                          //step
        0,                          //count
}; 

strobetime_para_t strobetime_para = { 
    .ov9282 =           {   
                            {0x3501, 0x0},	        //expo H		
                            {0x3502, 0x0},          //expo L
                            {0x3509, 0x0},          //gain
                        },   
    .ov9282_strobe =    {   
                            {0x3927, 0x0},	        // strobe width		
                            {0x3928, 0x0},          // 
                            {0x3929, 0x0},          // strobe start time
                            {0x392A, 0x0},          //
                        },
}; 

scan_cfg_t scan_cfg = SCAN_PARA_NO_NEED_INC;

trav_cfg_t trav_cfg = TRAV_PARA_NO_NEED_CHG;

strobe_cfg_t strobe_cfg = STROBE_PARA_NO_NEED_CHG;


static void led_current_command_usage(const char *prog)
{
    printf("  Usage: %s [OPTIONS]\r\n", prog);
    printf("  Options:\r\n");
    printf("  set [ir|spk]  value(0x00~0xFF)    Set ir|spk led current\r\n");
    printf("  get [ir|spk]                      Get ir|spk led current\r\n");
    printf("\r\n");
}

#ifndef AOS_BOARD_TX510_EG_SD
void ov9282_command_usage(const char *prog)
{
    printf("  Usage: %s [OPTIONS]\r\n", prog);
    printf("  Options:\r\n");
    printf("  set reg value                     Set ov9282 reg value\r\n");
    printf("  get reg                           Get ov9282 reg value\r\n");
    printf("\r\n");
}
#endif
static void para_scan_command_usage(const char *prog)
{
    printf("  Usage: %s [OPTIONS]\r\n", prog);
    printf("  Options:\r\n");
    printf("  ir spk expH expL gain step count  Set ir spk expH expL gain as initial value,\r\n");
    printf("                                    step as step-size, to increase count times.\r\n");
    printf("\r\n");
}

static void para_set_command_usage(const char *prog)
{
    printf("  Usage: %s [OPTIONS]\r\n", prog);
    printf("  Options:\r\n");
    printf("  cur ir spk                        Set ir|spk current values\r\n");
    printf("  time start end (1-33)             Set expo time select range\r\n");
    printf("  gain start end (1-16)             Set gain select range\r\n");
    printf("  start                             Start para traverse\r\n");
    printf("\r\n");
}

static void snapshot_command_usage(const char *prog)
{
    printf("  Usage: %s [OPTIONS]\r\n", prog);
    printf("  Options:\r\n");
    printf("  start                             Start snapshot task\r\n");
    printf("  Stop                              Stop snapshot task\r\n");
    printf("\r\n");
}

static void strobetime_command_usage(const char *prog)
{
    printf("  Usage: %s [OPTIONS]\r\n", prog);
    printf("  Options:\r\n");
    printf("  set x(dec) y(hex)                 Set strobe time to xms, gain y\r\n");
    printf("\r\n");
}

static int set_led_current(int argc, char **argv)
{
    uint32_t reg = 0;
    uint32_t val = 0;

    if (!strcmp(argv[2], "ir")) {
        cli_printf("set ir current.\n");
        reg = IR_CURRENT_REG;
    } else if (!strcmp(argv[2], "spk")) {
        cli_printf("set spk current.\n");
        reg = SPK_CURRENT_REG;
    } else {
        cli_printf("param invalid!\n");
        return -1;
    }
    val = strtoul(argv[3], NULL, 16);
    led_config_reglist(reg, val);
    g_led_config = LED_NEED_CONFIG;

    return 0;
}


static int get_led_current(int argc, char **argv)
{
    uint32_t reg = 0;
    uint32_t val = 0;
    double current = 0;

    if (!strcmp(argv[2], "ir")) {
        cli_printf("get ir current");
        reg = IR_CURRENT_REG;
    } else if (!strcmp(argv[2], "spk")) {
        cli_printf("get spk current");
        reg = SPK_CURRENT_REG;
    } else {
        cli_printf("param invalid!\n");
        return -1;
    }
    val = led_lookup_reg(reg);
    current = (val * CURRENT_MUL) + CURRENT_ADD;
    cli_printf(" = %f mA\n", current);

    return 0;
}

void led_current_command(char *outbuf, int len, int argc, char **argv)
{
    if (argc == 1) {
        led_current_command_usage(argv[0]);
        return;
    }
    if (!strcmp(argv[1], "set")) {
        set_led_current(argc, argv);
    } else if (!strcmp(argv[1], "get")) {
        get_led_current(argc, argv);
    } else {
        cli_printf("param invalid!\n");
        return;
    }

    return;
}

void pack_scan_para_list(uint8_t *buf)
{
	*(buf + 0) = scan_para_list.ir.data; 
	*(buf + 1) = scan_para_list.spk.data; 
	*(buf + 2) = scan_para_list.ov9282[0].data; 
	*(buf + 3) = scan_para_list.ov9282[1].data; 
	*(buf + 4) = scan_para_list.ov9282[2].data; 
}


void print_scan_para(void)
{
    printf("ir = 0x%x\n", scan_para_list.ir.data);
    printf("spk = 0x%x\n", scan_para_list.spk.data);
    printf("expH = 0x%x\n", scan_para_list.ov9282[0].data);
    printf("expL = 0x%x\n", scan_para_list.ov9282[1].data);
    printf("gain = 0x%x\n", scan_para_list.ov9282[2].data);
    printf("step = %d\n", scan_para_list.step);
    printf("count = %d\n", scan_para_list.count);
}

void para_scan_command(char *outbuf, int len, int argc, char **argv)
{
    if (argc == 1) {
        para_scan_command_usage(argv[0]);
        return;
    }
    scan_para_list.ir.data = strtoul(argv[1], NULL, 16);
    scan_para_list.spk.data = strtoul(argv[2], NULL, 16);
    scan_para_list.ov9282[0].data = strtoul(argv[3], NULL, 16);
    scan_para_list.ov9282[1].data = strtoul(argv[4], NULL, 16);
    scan_para_list.ov9282[2].data = strtoul(argv[5], NULL, 16);
    scan_para_list.step = strtoul(argv[6], NULL, 10);
    scan_para_list.count = strtoul(argv[7], NULL, 10);
    print_scan_para();
    para_inc_task_init();

    scan_cfg = SCAN_PARA_NEED_INC;

    return;
}

static int set_cur_val(int argc, char **argv)
{
    if (argc > 4) {
        cli_printf("param too much!\n");
        return -1;
    }
    traverse_para.ir.data = strtoul(argv[2], NULL, 16);
    traverse_para.spk.data = strtoul(argv[3], NULL, 16);

    printf("ir = %x\n", traverse_para.ir.data);
    printf("spk = %x\n", traverse_para.spk.data);
    led_config_reglist(traverse_para.ir.addr,  traverse_para.ir.data);
    led_config_reglist(traverse_para.spk.addr,  traverse_para.spk.data);

    g_led_config = LED_NEED_CONFIG;

    return 0;
}

static int set_expo_time_range(int argc, char **argv)
{   
    if (argc > 4) {
        cli_printf("param too much!\n");
        return -1;
    }

    traverse_para.exp_start = strtoul(argv[2], NULL, 10) - 1;
    traverse_para.exp_end = strtoul(argv[3], NULL, 10) - 1;
    printf("start = %d\n", traverse_para.exp_start + 1);
    printf("end = %d\n", traverse_para.exp_end + 1);

    return 0;
}

static int set_gain_range(int argc, char **argv)
{
    if (argc > 4) {
        cli_printf("param too much!\n");
        return -1;
    }

    traverse_para.gain_start = strtoul(argv[2], NULL, 10) - 1;
    traverse_para.gain_end = strtoul(argv[3], NULL, 10) - 1;
    printf("start = %d\n", traverse_para.gain_start + 1);
    printf("end = %d\n", traverse_para.gain_end + 1);

    return 0;
}

static int start_para_traverse(int argc, char **argv)
{
    if (argc > 3) {
        cli_printf("param too much!\n");
        return -1;
    }
    para_traverse_task_init();
    trav_cfg = TRAV_PARA_NEED_CHG;

    return 0;
}

void para_set_command(char *outbuf, int len, int argc, char **argv)
{
    if (argc == 1) {
        para_set_command_usage(argv[0]);
        return;
    }
    if (!strcmp(argv[1], "cur")) {
        set_cur_val(argc, argv);
    } else if (!strcmp(argv[1], "time")) {
        set_expo_time_range(argc, argv);
    } else if (!strcmp(argv[1], "gain")) {
        set_gain_range(argc, argv);
    } else if (!strcmp(argv[1], "start")) {
        start_para_traverse(argc, argv);
    } else {
        cli_printf("param invalid!\n");
        return;
    }

    return;
}

static void snapshot_task(void *param)
{
	const char *task_name = aos_task_name();
	printf("task name: %s start!\r\n", task_name);

    while (1) {
        vi_set_snap_mode(SNAPSHOT_MODE_3IN1);
        while(1) {
            if(vi_get_snap_status())
            {
                printf("snap-task: get status done \n");
            }	
            aos_msleep(1);
        }
        vi_set_snap_mode(SNAPSHOT_MODE_DONE);
        aos_msleep(1);
    }
}

#define SNAPSHOT_MODULE "snapshot"

void snapshot_task_init(void)
{
    aos_task_new(SNAPSHOT_MODULE, snapshot_task, NULL, 10*1024);  

    return;
}

static int snapshot_task_start(int argc, char **argv)
{
    snapshot_task_init();

    return 0;
}

static int snapshot_task_stop(int argc, char **argv)
{
    aos_task_delete(SNAPSHOT_MODULE);
    printf("%s delete!\n", SNAPSHOT_MODULE);

    return 0;
}


void snapshot_command(char *outbuf, int len, int argc, char **argv)
{
    if (argc == 1) {
        snapshot_command_usage(argv[0]);
        return;
    }
    if (!strcmp(argv[1], "start")) {
        snapshot_task_start(argc, argv);
    } else if (!strcmp(argv[1], "stop")) {
        snapshot_task_stop(argc, argv);
    } else {
        cli_printf("param invalid!\n");
        return;
    }

    return;
}

void strobetime_command(char *outbuf, int len, int argc, char **argv)
{
    int ms = 0;
    int gain = 0;

    if (argc == 1) {
        strobetime_command_usage(argv[0]);
        return;
    }
    if (!strcmp(argv[1], "set")) {
        ms = strtoul(argv[2], NULL, 10);
        gain = strtoul(argv[3], NULL, 16);
        printf("set %dms, 0x%x gain", ms, gain);
        strobetime_para.ov9282[0].data = expo_para_list[ms].expo[0];                       /* expoH */
        strobetime_para.ov9282[1].data = expo_para_list[ms].expo[1];                       /* expoL */
        strobetime_para.ov9282[2].data = gain;                                             /* gain */
        strobetime_para.ov9282_strobe[0].data = strobe_para_list[ms].strobe[0];
        strobetime_para.ov9282_strobe[1].data = strobe_para_list[ms].strobe[1];
        strobetime_para.ov9282_strobe[2].data = strobe_para_list[ms].strobe[2];
        strobetime_para.ov9282_strobe[3].data = strobe_para_list[ms].strobe[3];
        strobe_cfg = STROBE_PARA_NEED_CHG;
    } else {
        cli_printf("param invalid!\n");
        return;
    }

    return;
}
